package com.explment.lens.config;

import com.explment.lens.filter.JwtAuthenticationFilter;
import com.explment.lens.service.security.SecurityUserDetailService;
import com.explment.lens.utils.result.ResultCode;
import com.explment.lens.utils.result.ResultData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;
import java.util.List;

@Configuration
@EnableWebSecurity
public class SecurityConfig{

    @Autowired
    private SecurityUserDetailService securityUserDetailService;

    @Autowired
    private PasswordEncoder passwordEncoder;


    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // 关闭跨站请求伪造防护
                .csrf(csrf-> csrf.disable())
                // 开启跨源资源共享
                .cors(cors -> cors.configurationSource(corsConfigurationSource()))
                // 配置授权请求
                .authorizeHttpRequests(auth->
                        auth.requestMatchers("/api/**","/error").permitAll()
                                .anyRequest().authenticated()) // 其他所有请求需要身份验证
                // 禁用session，不创建session，只依赖token
                .sessionManagement(session-> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
               // 添加自定义 前缀过滤器
                .addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .exceptionHandling(exception-> exception.authenticationEntryPoint((request, response, authException) -> {
                    response.setStatus(401);
                    response.setCharacterEncoding("UTF-8");
                    response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                    response.getWriter().write(ResultData.fail(ResultCode.UNAUTHORIZED,"无权访问").toString());
                }))
                // 禁用默认登录页
                .formLogin(AbstractHttpConfigurer::disable)
                // 配置登出请求
                .logout(logout-> logout.logoutUrl("/logout").permitAll()); // 设置登出URL为 /logout，允许所有访问登出URL的请求
        return http.build();
    }


    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(securityUserDetailService).passwordEncoder(passwordEncoder);
    }
    @Bean
    public AuthenticationManager authManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }

    /**
     * 创建一个跨域资源共享（CORS）配置源。
     * security 的跨域请求
     * @return CorsConfigurationSource 跨域资源共享配置源
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        // 设置允许的源(前端)地址，可以根据实际需求进行修改
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setExposedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        configuration.setMaxAge(3600L);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

}
